import os
import sys
import pandas as pd

def preprocess_csv(file_path):
    """
    对单个 CSV 文件进行预处理，当前仅简单读取，可根据需求扩展
    :param file_path: CSV 文件路径
    :return: 处理后的数据框
    """
    try:
        # 尝试使用GBK编码读取CSV文件（适用于中文编码）
        # 尝试多种编码读取文件
            encodings = ['gbk', 'utf-8', 'iso-8859-1', 'gb2312']
            df = None
            for encoding in encodings:
                try:
                    df = pd.read_csv(file_path, encoding=encoding, sep=',', header=None)
                    break
                except UnicodeDecodeError:
                    continue
            if df is None:
                print(f"处理文件 {file_path} 时出错: 所有编码尝试均失败")
                return pd.DataFrame()
            # 将空值填充为"error"
            df = df.fillna("error")
            
            # 验证列数，确保不超过11列
            if df.shape[1] > 11:
                print(f"处理文件 {file_path} 时发现异常数据: 列数为{df.shape[1]}，预期不超过11列")
                # 截取前11列保留有效数据
                df = df.iloc[:, :11]
            elif df.shape[1] < 11:
                # 对于列数不足的空行，补充至11列
                missing_cols = 11 - df.shape[1]
                for i in range(missing_cols):
                    df[f'补充列_{i+1}'] = "error"
            
            return df
        # 这里可以添加更多的预处理步骤，例如数据清洗、转换等
        # 示例：去除包含空值的行
            df = df.dropna()
            return df
    except Exception as e:
        print(f"处理文件 {file_path} 时出错: {e}")
        return pd.DataFrame()

def process_data(root_dir):
    """
    处理指定目录下所有按分钟时间分桶的文件夹中的 CSV 文件
    :param root_dir: 根目录路径
    :return: 合并后的处理结果数据框
    """
    all_data = []
    
    # 遍历根目录下的所有文件夹
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for filename in filenames:
            if filename.endswith('.csv'):
                file_path = os.path.join(dirpath, filename)
                processed_df = preprocess_csv(file_path)
                if not processed_df.empty:
                    all_data.append(processed_df)
    
    # 合并所有处理后的数据
    if all_data:
        combined_df = pd.concat(all_data, ignore_index=True)
        return combined_df
    return pd.DataFrame()

if __name__ == "__main__":
    root_directory = '/data/GuoCu_data/'
    result = process_data(root_directory)
    if result.empty:
        print("未找到有效数据或处理过程中出现错误。")
        sys.exit(1)
    
    # 筛选曝光事件(viewport)和点击事件(click)
    # 假设事件类型在第二列(索引1)
    exposure_df = result[result.iloc[:, 1] == 'viewport'].copy()
    click_df = result[result.iloc[:, 1] == 'click'].copy()
    
    if exposure_df.empty:
        print("未找到曝光事件数据。")
        sys.exit(1) 
    
    # 移除eventTime处理，不进行时间格式转换和时间阈值判断
    
    # 添加时间阈值判断（1分钟）
    TIME_THRESHOLD = 30000  # 单位：秒
    
    # 解析eventTime列（假设eventTime在第9列，索引8）
    exposure_df['eventTime'] = pd.to_datetime(exposure_df.iloc[:, 8], errors='coerce')
    # 过滤无效时间数据
    # 仅过滤点击事件的无效时间，保留所有曝光事件
    click_df['eventTime'] = pd.to_datetime(click_df.iloc[:, 8], errors='coerce')
    click_df = click_df.dropna(subset=['eventTime'])
    
    # 为曝光事件添加label列，默认为0
    exposure_df['label'] = 0
    
    # 如果没有点击事件，直接保存结果
    if not click_df.empty:
        # 按IP(5列)、pageId(6列)、sceneId(7列)、elementId(8列)分组
        # 新增：第4列Id、第5列Ip_addr、第9列tenantId、第10列trackingMappingId、第11列userId
        group_cols = [result.columns[3], result.columns[4], result.columns[5], result.columns[6], result.columns[7], result.columns[8], result.columns[10]]
        click_groups = click_df.groupby(group_cols)
        
        # 遍历每个曝光事件查找匹配的点击事件
        for idx, exp_row in exposure_df.iterrows():
            # 获取当前曝光事件的关键信息（包含新增匹配维度）
            key = (exp_row.iloc[3], exp_row.iloc[4], exp_row.iloc[5], exp_row.iloc[6], exp_row.iloc[7], exp_row.iloc[8], exp_row.iloc[10])
            
            # 检查是否有匹配的点击事件组
            if key in click_groups.groups:
                # 获取该组内的所有点击事件
                clicks = click_df.loc[click_groups.groups[key]]
                
                # 解析曝光事件时间并检查有效性
                exp_time = pd.to_datetime(exp_row.iloc[8], errors='coerce')
                if pd.notna(exp_time):
                    # 计算时间差并判断是否在阈值内
                    time_diff = (clicks['eventTime'] - exp_time).dt.total_seconds()
                    valid_clicks = clicks[(time_diff >= 0) & (time_diff <= TIME_THRESHOLD)]
                    if not valid_clicks.empty:
                        exposure_df.at[idx, 'label'] = 1
    
    # 创建输出目录
    output_dir = '/data/GuoCu_data/withLabel_data'
    os.makedirs(output_dir, exist_ok=True)
    output_path = os.path.join(output_dir, 'labeled_exposures.csv')
    
    # 保存结果
    try:
        exposure_df.to_csv(output_path, index=False, encoding='gbk', header=False)
        print(f"预处理完成，带标签的曝光数据已保存至: {output_path}")
        print(f"共处理 {len(exposure_df)} 条曝光数据，其中 {exposure_df['label'].sum()} 条匹配到点击事件")
    except Exception as e:
        print(f"保存文件时出错: {e}")
